package es.xpt.ysf.view.collections;

import java.util.Iterator;

import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;

import es.xpt.ysf.jaas.PrivilegesChecker;
import es.xpt.ysf.utils.ServiceLocatorException;
import es.xpt.ysf.view.model.ApplicationViewBean;

public class CollectionResolver extends ELResolver {

	public Object getValue(ELContext context, Object base, Object property)
			throws ELException {
		
		if (context == null)
			throw new NullPointerException();
		

		  if(base == null) {
	            // Resolving first variable (e.g. #{Collections}).  
	            // We only handle "Collections"
	            String propertyName = (String)property;
	            if(propertyName.equals("Collections")) {
	            	ApplicationViewBean apb = (ApplicationViewBean)context.getELResolver().getValue(context, null, "ApplicationBean");
	            	context.setPropertyResolved(true);
	                return apb.getCollections();
	            } else if (propertyName.equals("Privileges")) {
	            	// Resuelvo el privilegio
	            	context.setPropertyResolved(true);
	            	return new PrivilegesChecker();
	            }
	       } else if(base instanceof YSFCollections) {
	    	   YSFCollections cols = (YSFCollections)base;
	    	   
	    	   if ( "numbers".equals((String)property) ) {
	    		   context.setPropertyResolved(true);
	    		   return new NumberCollectionsMethod();
	    	   }
	    	   
	    	   CollectionInfo ci = cols.get((String)property);
	    	   if ( ci == null ) 
	    		   throw new ELException("Collection "  + property + " not found.");
	    	   
	    	   context.setPropertyResolved(true);
	    	   	
	    	   switch ( ci.getType()) {
	    	   		case ENUMERATION:
		    	   		try {
		    	   			return ci.resolveEnumeration();
		    	   		} catch (ServiceLocatorException e) {
			 	    	   throw new ELException(e);
		    	   		}
	    	   		case STATIC:
	    	   			ci.getMethod().clearArgs();
	    	   			if ( ci.getMethod().isReady() ) {
	    	   				try {
								return ci.getMethod().staticInvoke();
							} catch (ServiceLocatorException e) {
								throw new ELException(e);
							}
	    	   			}
	    	   			return  ci.getMethod();
	    	   		case SERVICE:
	    	   			ci.getMethod().clearArgs();
	    	   			if ( ci.getMethod().isReady() ) {
	    	   				try {
								return ci.getMethod().invoke();
							} catch (ServiceLocatorException e) {
								throw new ELException(e);
							}
	    	   			}
	    	   			return  ci.getMethod();
	    	   		}
	       } else if(base instanceof ResolvedMethod) {
	    	   ResolvedMethod rm = (ResolvedMethod) base;
	    	   rm.addArg(property);
	    	   context.setPropertyResolved(true);
	    	   if ( rm.isReady() ) {
	   				try {
	   					if ( rm.getClassName()!=null ) 
	   						return rm.staticInvoke();
						else 
							return rm.invoke();
					} catch (ServiceLocatorException e) {
						throw new ELException(e);
					}
	   			}
	   			return  rm;
	       } else if (base instanceof PrivilegesChecker) {
	    	   PrivilegesChecker privilegesChecker = (PrivilegesChecker) base;
	    	   context.setPropertyResolved(true);
	    	   return privilegesChecker.isActionGranted((String) property);
	       }
		return null;
	}

	public Class<?> getType(ELContext context, Object base, Object property) throws ELException {
		return null;
	}

	public void setValue(ELContext context, Object base, Object property, Object value) throws ELException {
	}

	public boolean isReadOnly(ELContext context, Object base, Object property) throws ELException {
		return true;
	}

	public Iterator<java.beans.FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
		return null;
	}

	public Class<?> getCommonPropertyType(ELContext context, Object base) {
		return null;
	}
}
